package com.atguigu.ware.service.impl;

import com.atguigu.common.constants.WareConstant;
import com.atguigu.ware.entity.PurchaseDetailEntity;
import com.atguigu.ware.service.PurchaseDetailService;
import com.atguigu.ware.service.WareSkuService;
import com.atguigu.ware.vo.MergerVo;
import com.atguigu.ware.vo.PurchaseDoneVo;
import com.atguigu.ware.vo.PurchaseItemDoneVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.ware.dao.PurchaseDao;
import com.atguigu.ware.entity.PurchaseEntity;
import com.atguigu.ware.service.PurchaseService;
import org.springframework.transaction.annotation.Transactional;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {

    @Autowired
    private PurchaseDetailService detailService;

    @Autowired
    private WareSkuService wareSkuService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>()
        );

        return new PageUtils(page);
    }


    /**
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPageUnreceive(Map<String, Object> params) {

        LambdaQueryWrapper<PurchaseEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PurchaseEntity::getStatus, WareConstant.PurchaseStatusEnum.CREATED.getCode())
                .or()
                .eq(PurchaseEntity::getStatus,  WareConstant.PurchaseStatusEnum.ASSIGNED.getCode());



        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }


    /**
     * 合并采购需求
     * @param mergerVo
     */
    @Transactional
    @Override
    public void mergePurchase(MergerVo mergerVo) {
        //分配，就是修改【采购需求】里对应的【采购单id、采购需求状态】，即purchase_detail表
        //并且不能重复分配采购需求给不同的采购单,如果还没去采购，或者采购失败，就可以修改

        Long purchaseId = mergerVo.getPurchaseId();
        if (Objects.isNull(purchaseId)) {
            //如果为空, 说明是没有采购订单的是一个空的采购订单
            PurchaseEntity purchaseEntity = new PurchaseEntity();

            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());
            this.save(purchaseEntity);
            purchaseId = purchaseEntity.getId();

        }

        //获取要合并的采购需求id合并项
        List<Long> items = mergerVo.getItems();
        Long finalPurchaseId = purchaseId;
        List<PurchaseDetailEntity> collect= detailService.listByIds(items).stream().filter(entity->{
            return entity.getStatus() < WareConstant.PurchaseDetailStatusEnum.BUYING.getCode()
                    || entity.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode();
        }).map((entity) -> {
            entity.setPurchaseId(finalPurchaseId);
            entity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
            return entity;
        }).collect(Collectors.toList());


        detailService.updateBatchById(collect);


    }

    @Transactional
    @Override
    public void received(List<Long> ids) {

        if (ids==null || ids.size()==0) {
            return ;
        }

        //1. 确认当前采购订单的状态是新建或者已分配状态
        List<PurchaseEntity> collect = ids.stream().map((id) -> {

            PurchaseEntity purchaseEntity = this.getById(id);
            return purchaseEntity;
        }).filter(item->{
           return  (item.getStatus()==WareConstant.PurchaseStatusEnum.CREATED.getCode()
                    ||
                    item.getStatus()==WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()
                   );
        }).map(item->{
            //2. 修改采购单的状态为已领取
            item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
            return item;
        }).collect(Collectors.toList());
        this.updateBatchById(collect);


        //3. 修改该采购单下的所有采购需求的状态为正在采购
        LambdaQueryWrapper<PurchaseDetailEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(PurchaseDetailEntity::getPurchaseId, ids);

        PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
        purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
        detailService.update(purchaseDetailEntity, queryWrapper);



    }

    @Transactional
    @Override
    public void done(PurchaseDoneVo vo) {

        Long id = vo.getId();


        Boolean flag = true;
        List<PurchaseItemDoneVo> items = vo.getItems();
        ArrayList<PurchaseDetailEntity> updates = new ArrayList<>();
        for (PurchaseItemDoneVo item : items) {
            PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
            if (item.getStatus()==WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()) {
                flag = false;
                detailEntity.setStatus(item.getStatus());
            }else {
                detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
                //3. 将采购成功的进行入库
                PurchaseDetailEntity purchaseDetail = detailService.getById(item.getItemId());
                wareSkuService.addStock(purchaseDetail.getSkuId(), purchaseDetail.getWareId(), purchaseDetail.getSkuNum());

            }
            detailEntity.setId(item.getItemId());
            updates.add(detailEntity);
        }
        //2. 修改采购项的状态
        detailService.updateBatchById(updates);

        //1. 修改采购单的状态
        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setId(id);

        purchaseEntity.setStatus(
                flag ? WareConstant.PurchaseStatusEnum.FINISH.getCode()
                :
                WareConstant.PurchaseStatusEnum.HASERROR.getCode());

        purchaseEntity.setUpdateTime(new Date());

        this.updateById(purchaseEntity);

    }

}